package com.example.uploadtest.webSocket;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.uploadtest.utils.BaseUtils;
import com.example.uploadtest.utils.WsUtil;
import com.example.uploadtest.webSocket.entity.pull.ChangeImgDto;
import com.example.uploadtest.webSocket.entity.pull.MoveImgDto;
import com.example.uploadtest.webSocket.entity.pull.PullCanvasDto;
import com.example.uploadtest.webSocket.entity.pull.PullMsgDto;
import com.example.uploadtest.webSocket.entity.push.BasePushDto;
import com.example.uploadtest.webSocket.entity.push.LoginAndOut;
import com.example.uploadtest.webSocket.entity.push.PushMsgDto;
import com.example.uploadtest.webSocket.entity.push.PushUserDto;
import com.example.uploadtest.webSocket.entity.service.ImgDto;
import com.example.uploadtest.webSocket.entity.service.UserDto;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@ServerEndpoint("/go/{group}/{userid}")
@Component
public class MyWebSocket {

    //分组容器
    private static ConcurrentMap<Integer, ConcurrentMap<String, Session>> channelMap = new ConcurrentHashMap<>();
    //channelid所在的组
    private static ConcurrentMap<String , UserDto> channelByGroup =new ConcurrentHashMap<>();
    //画板缓存
    private static ConcurrentMap<Integer , ArrayList<PullCanvasDto>>canvse= new ConcurrentHashMap<>();
    //背景图片缓存
    private static ConcurrentMap<Integer , ImgDto> img = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session  session, @PathParam("group") Integer group, @PathParam("userid") String userid) throws IOException {

                if(BaseUtils.isNotBlank(userid) && null!=group){
                    //存入分组
                    if(channelMap.get(group)==null){
                        ConcurrentMap<String, Session> map = new ConcurrentHashMap<>();
                        map.put(userid,session);
                        channelMap.put(group,map);
                    }else{
                        channelMap.get(group).put(userid,session);
                    }
                    //根据session获取用户消息
                    UserDto userDto = new UserDto();
                    userDto.setGroup(group);
                    userDto.setUserid(userid);
                    channelByGroup.put(session.getId(),userDto);
                    //回复登录成功
                    session.getBasicRemote().sendText(WsUtil.LoginSuccess());
                    //上线通知
                    ConcurrentMap<String, Session> channelConcurrentMap = channelMap.get(userDto.getGroup());
                    BasePushDto send = new BasePushDto();
                    send.setType(3);
                    LoginAndOut loginAndOut = new LoginAndOut();
                    loginAndOut.setUserid(userDto.getUserid());
                    loginAndOut.setActiveCount(channelConcurrentMap.size());
                    send.setData(loginAndOut);
                    for (String s : channelConcurrentMap.keySet()) {
                        channelConcurrentMap.get(s).getBasicRemote().sendText(JSON.toJSONString(send));
                    }
                }else{
                    session.close();
                }
    }

    @OnMessage
    public void onMessage(String msg, Session session) throws IOException {

        Integer type=null;
        String date=null;
        try {
            JSONObject jsonObject = JSON.parseObject(msg);
            type=Integer.valueOf(jsonObject.get("type").toString());
            if(null!=jsonObject.get("data")){
                date= jsonObject.get("data").toString();
            }
        }catch (Exception e){session.close();}
        if(type==null){
            session.close();
        }
         UserDto userDto = channelByGroup.get(session.getId());
         if(null==userDto){
             session.close();
         }else{
             //发送消息
             if (type == 2) {
                 MsgHandler(userDto, JSON.parseObject(date, PullMsgDto.class));
             }
             //画板动作
             else if (type == 3) {
                 CanvasHandler(userDto, JSON.parseObject(date, PullCanvasDto.class));
             }
             //拉取画板缓存
             else if (type == 4 ){
                 ArrayList<PullCanvasDto> set = canvse.get(userDto.getGroup());
                 BasePushDto send = new BasePushDto();
                 send.setType(5);
                 if(set!=null){
                     for (PullCanvasDto s : set) {
                         send.setData(s);
                         session.getBasicRemote().sendText( JSON.toJSONString(send));
                     }
                 }
             }
             //切背景图
             else if(type == 5){
                 ChangeImgHandler(userDto, JSON.parseObject(date, ChangeImgDto.class));
             }
             //移动背景图
             else if(type == 6){
                 MoveImgHandler(userDto, JSON.parseObject(date, MoveImgDto.class));
             }
             //清除自己的画板
             else if(type == 7){
                 ClearUsHandler(userDto);
                 //清空所有画板
             }else if(type == 8 ){
                 ClearAllHandler(userDto);
             }
             //拉取背景图片缓存
             else if(type ==9){
                 BasePushDto send = new BasePushDto();
                 send.setType(10);
                 ImgDto imgDto = img.get(userDto.getGroup());
                    if(null!=imgDto) {
                        send.setData(img.get(userDto.getGroup()));
                    }
                 session.getBasicRemote().sendText(JSON.toJSONString(send));
             }else{
                 session.close();
             }
         }
    }

    @OnClose
    public void onClose( Session session) throws IOException {
        UserDto userDto = channelByGroup.get(session.getId());
        //关闭连接
        channelByGroup.remove(session.getId());
        //通知掉线
        ConcurrentMap<String, Session> channelConcurrentMap = channelMap.get(userDto.getGroup());
        channelConcurrentMap.remove(userDto.getUserid());
        BasePushDto send = new BasePushDto();
        send.setType(4);
        LoginAndOut loginAndOut = new LoginAndOut();
        loginAndOut.setUserid(userDto.getUserid());
        loginAndOut.setActiveCount(channelConcurrentMap.size());
        send.setData(loginAndOut);
        for (String s : channelConcurrentMap.keySet()) {
            channelConcurrentMap.get(s).getBasicRemote().sendText(JSON.toJSONString(send));
        }


    }

    //清空所有画板
    private void ClearAllHandler(UserDto userDto) throws IOException {
        ConcurrentMap<String, Session> map = channelMap.get(userDto.getGroup());
        BasePushDto basePushDto = new BasePushDto();
        PushUserDto clearUsDto = new PushUserDto();
        clearUsDto.setUserid(userDto.getUserid());
        basePushDto.setData(clearUsDto);
        basePushDto.setType(9);
        for (String s : map.keySet()) {
            if(!s.equals(userDto.getUserid())) {//清除所有的画板不用发给自己
                map.get(s).getBasicRemote().sendText(JSON.toJSONString(basePushDto));
            }
        }
        //清空画板缓存
        canvse.get(userDto.getGroup()).clear();
    }

    //清除自己的画板
    private void ClearUsHandler(UserDto userDto) throws IOException {
        ConcurrentMap<String, Session> map = channelMap.get(userDto.getGroup());
        BasePushDto basePushDto = new BasePushDto();
        PushUserDto clearUsDto = new PushUserDto();
        clearUsDto.setUserid(userDto.getUserid());
        basePushDto.setType(8);
        basePushDto.setData(clearUsDto);
        for (String s : map.keySet()) {
            if(!s.equals(userDto.getUserid())) {//清除自己的画板不用发给自己
                map.get(s).getBasicRemote().sendText (JSON.toJSONString(basePushDto));
            }
        }
        //更新缓存
        WsUtil.ClearUsLocal(canvse,userDto.getUserid(),userDto.getGroup());

    }

    //移动背景
    private void MoveImgHandler(UserDto userDto, MoveImgDto parseObject) throws IOException {
        ConcurrentMap<String, Session> map = channelMap.get(userDto.getGroup());
        BasePushDto basePushDto = new BasePushDto();
        basePushDto.setType(7);
        basePushDto.setData(parseObject);

        for (String s : map.keySet()) {
            if(!s.equals(userDto.getUserid())) {//移动背景不用发给自己
                map.get(s).getBasicRemote().sendText(JSON.toJSONString(basePushDto));
            }
        }
        //更新移动背景缓存
        ImgDto imgDto = img.get(userDto.getGroup());
        if(null!=imgDto){
            imgDto.setX(parseObject.getX());
            imgDto.setY(parseObject.getY());
        }

    }

    //切背景图
    private void ChangeImgHandler(UserDto userDto, ChangeImgDto parseObject) throws IOException {
        //只在当前分组发
        ConcurrentMap<String, Session> map = channelMap.get(userDto.getGroup());
        BasePushDto basePushDto = new BasePushDto();
        parseObject.setUserid(userDto.getUserid());
        basePushDto.setType(6);
        basePushDto.setData(parseObject);
        for (String s : map.keySet()) {
            if(!s.equals(userDto.getUserid())) {//切换背景不用发给自己
                map.get(s).getBasicRemote().sendText( JSON.toJSONString(basePushDto));
            }
        }
        //更新背景图片缓存
        ImgDto imgDto = img.get(userDto.getGroup());
        if(null==imgDto){
            ImgDto imgDto1 = new ImgDto();
            imgDto1.setImgurl(parseObject.getUrl());
            imgDto1.setX(0);
            imgDto1.setY(0);
            img.put(userDto.getGroup(),imgDto1);
        }else{
            imgDto.setImgurl(parseObject.getUrl());
        }

    }

    //画板动作
    private void CanvasHandler(UserDto userDto, PullCanvasDto pullCanvasDto) throws IOException {

        //缓存画板
        if( canvse.get(userDto.getGroup())==null){
            ArrayList<PullCanvasDto> c = new ArrayList<>();
            c.add(pullCanvasDto);
            canvse.put(userDto.getGroup(),c);
        }else{
            canvse.get(userDto.getGroup()).add(pullCanvasDto);
        }

        //只在当前分组发
        ConcurrentMap<String, Session> map = channelMap.get(userDto.getGroup());
        BasePushDto send = new BasePushDto();
        send.setType(5);
        send.setData(pullCanvasDto);
        System.out.println("1");
        for (String s : map.keySet()) {
            if(!s.equals(userDto.getUserid())){//画板动作不用发给自己
               // map.get(s).getBasicRemote().sendText(JSON.toJSONString(send));
                map.get(s).getAsyncRemote().sendText(JSON.toJSONString(send));
            }
        }
        System.out.println("2");
    }

    //发送消息
    private void MsgHandler(UserDto userDto, PullMsgDto pullMsgDto) throws IOException {
        //只在当前分组发
        ConcurrentMap<String, Session> map = channelMap.get(userDto.getGroup());
        BasePushDto send = new BasePushDto();
        send.setType(2);
        PushMsgDto sendMsgDto = new PushMsgDto();
        sendMsgDto.setMsg(pullMsgDto.getMsg());
        sendMsgDto.setUserid(userDto.getUserid());
        send.setData(sendMsgDto);
        for (String s : map.keySet()) {
            map.get(s).getBasicRemote().sendText(JSON.toJSONString(send));
        }
    }


}
